// go-api-server
package apiserver

import (
	"errors"
	"strconv"
	"strings"

	"yingsheng.com/go-api-server/context"
)

type controllerFuncInfo struct {
	fn     func()
	method []string
}

// 服务模块接口
type ControllerInterface interface {
	Init(*context.Context)
	Prepare()
	Finish()
	HandlerFunc(fn string) error
	FuncMapping()
}

// 服务模块控制器基类
type Controller struct {
	*context.Context

	// 服务方法的路由对象
	funcMapping map[string]controllerFuncInfo
	funcName    string
}

func (c *Controller) Init(ctx *context.Context) {
	c.Context = ctx
	c.funcMapping = make(map[string]controllerFuncInfo)
}

func (c *Controller) Prepare() {}

func (c *Controller) Finish() {}

func (c *Controller) IsFunc(fnName ...string) bool {
	if len(c.funcName) == 0 {
		acts := strings.Split(c.Request.Action(), ".")
		c.funcName = acts[len(acts)-1]
	}

	isFunc := false
	for _, v := range fnName {
		if strings.EqualFold(c.funcName, v) {
			isFunc = true
			break
		}
	}

	return isFunc
}

// HandlerFunc call function with the name
func (c *Controller) HandlerFunc(fnname string) error {
	if v, ok := c.funcMapping[fnname]; ok {

		isRun := false
		method := c.Request.Method()
		for i, n := 0, len(v.method); i < n; i++ {
			if method == v.method[i] {
				v.fn()
				isRun = true
				break
			}
		}

		if !isRun {
			return errors.New("不存在接口")
		}

		return nil
	}
	return errors.New("不存在接口")
}

// MethodMapping register the internal Controller router.
func (c *Controller) FuncMapping() {}

func (c *Controller) GetMapping(name string, fn func()) {
	c.mapping(name, fn, "GET")
}

func (c *Controller) PostMapping(name string, fn func()) {
	c.mapping(name, fn, "POST")
}

// 注册方法
// method可以是 GET 或 POST，默认两个都包含，大小写不限
func (c *Controller) mapping(name string, fn func(), method ...string) {
	n := len(method)
	if n == 0 {
		method = append(method, "GET")
		method = append(method, "POST")
	} else {
		m := ""
		for i := 0; i < n; i++ {
			m = strings.ToUpper(method[i])
			if m == "GET" || m == "POST" {
				method = append(method, m)
			}
		}
	}

	c.funcMapping[strings.ToLower(name)] = controllerFuncInfo{fn: fn, method: method}
}

// 将参数填充到结构体中
func (c *Controller) ParseStruct(obj interface{}) error {
	return c.Request.Params().ParseStruct(obj)
}

// 将参数集合转换为map对象
func (c *Controller) ParseMap() map[string]interface{} {
	return c.Request.Params().ParseMap()
}

// 获取参数
func (c *Controller) GetParam(key string) (string, bool) {
	return c.Request.Params().Get(key)
}

// 获取字符串参数
func (c *Controller) GetString(key string, def ...string) string {
	p, ok := c.GetParam(key)
	if !ok {
		if len(def) == 1 {
			return def[0]
		}
		return ""
	}
	return p
}

// 获取int型参数
func (c *Controller) GetInt(key string, def ...int) (int, error) {
	p := c.GetString(key)
	if len(p) == 0 && len(def) == 1 {
		return def[0], nil
	}
	return strconv.Atoi(p)
}

// 获取int64型参数
func (c *Controller) GetInt64(key string, def ...int64) (int64, error) {
	p := c.GetString(key)
	if len(p) == 0 && len(def) == 1 {
		return def[0], nil
	}
	return strconv.ParseInt(p, 10, 64)
}

// 获取float64型参数
func (c *Controller) GetFloat64(key string, def ...float64) (float64, error) {
	p := c.GetString(key)
	if len(p) == 0 && len(def) == 1 {
		return def[0], nil
	}
	return strconv.ParseFloat(p, 64)
}

// 获取bool型参数
func (c *Controller) GetBool(key string, def ...bool) (bool, error) {
	p := c.GetString(key)
	if len(p) == 0 && len(def) == 1 {
		return def[0], nil
	}
	return strconv.ParseBool(p)
}

// 添加结果
func (c *Controller) Put(key string, value interface{}) {
	c.Response.Result().Put(key, value)
}

// 设置错误信息
func (c *Controller) Error(options ...interface{}) {
	c.Response.Error(options...)
}

// 停止运行，会终止后面的运行内容及事件
// 会执行 WriteJson
func (c *Controller) Stop() {
	c.Context.Stop()
}

// 检查登录状态，未登录会自动终结
func (c *Controller) CheckLogin() {
	if isLogin, err := c.UserSession.CheckLogin(); !isLogin {
		if err != nil {
			c.Error(err)
		} else {
			c.Error(c.UserSession.GetLoginStatus())
		}
		c.Stop()
	}
}

// 检查企业成员状态，不存在的会自动终结
func (c *Controller) CheckCorpMember(companyId string) {
	if isMember, err := c.UserSession.CheckCorpMember(companyId); !isMember {
		if err != nil {
			c.Error(err)
		} else {
			c.Error(c.UserSession.GetCorpMemberStatus())
		}
		c.Stop()
	}
}

// 检查是否企业超级管理员，非管理员会自动终结
// 会前置调用 CheckCorpMember
func (c *Controller) CheckCorpAdmin(companyId string) {
	if isAdmin, err := c.UserSession.CheckCorpAdmin(companyId); !isAdmin {
		if err != nil {
			c.Error(err)
		} else {
			c.Error(c.UserSession.GetCorpAdminStatus())
		}
		c.Stop()
	}
}
